package top.wugy.blog.kits;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jfinal.json.Jackson;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.pegdown.Extensions;
import org.pegdown.PegDownProcessor;

import java.security.MessageDigest;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * wugy on 2017/11/3 14:19
 */
public class BlogKit {

    private static final String MD5 = "MD5";

    private static byte[] encodeMD5(String data) throws Exception {
        MessageDigest md = MessageDigest.getInstance(MD5);
        return md.digest(data.getBytes());
    }

    private static final char[] hexDigits = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    private static String convert2Hex(byte[] data) {
        char[] str = new char[data.length * 2];
        int k = 0;
        for (byte byte0 : data) {
            str[(k++)] = hexDigits[(byte0 >>> 4 & 0xF)];
            str[(k++)] = hexDigits[(byte0 & 0xF)];
        }
        return new String(str);
    }

    public static String encodeMD5Hex(String data) {
        try {
            return convert2Hex(encodeMD5(data));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Date now() {
        return new Date();
    }

    public static String jwtToken(Integer userId) {
        Date now = now();
        Date expireDate = new Date(now.getTime() + Const.JWT_EXPIRE * 1000);
        return Jwts.builder().setHeaderParam("tpy", "JWT").setSubject(userId + "").setIssuedAt(now)
                .setExpiration(expireDate).signWith(SignatureAlgorithm.HS512, Const.JWT_SECRET).compact();
    }

    public static Claims getClaimsByToken(String token) {
        return Jwts.parser().setSigningKey(Const.JWT_SECRET).parseClaimsJws(token).getBody();
    }

    public static String date2Str(Date date) {
        return date2Str(date, Const.DEF_DATE_FORMAT);
    }

    public static String date2Str(Date date, String pattern) {
        if (null == date)
            return "";
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault())
                .format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 获取月份最后的一天
     *
     * @param month 月份（格式：yyyy-MM）
     */
    public static LocalDate getLastDay(String month) {
        month = month + "-01";
        //本月的第一天
        LocalDate firstDate = LocalDate.parse(month, DateTimeFormatter.ofPattern(Const.DATE_FORMAT));
        return firstDate.with(TemporalAdjusters.lastDayOfMonth());
    }

    public static boolean isExpire(Date expiration) {
        return expiration.before(now());
    }

    private static Date toDate(String time) {
        LocalDate localDate = LocalDate.parse(time, DateTimeFormatter.ofPattern(Const.DEF_DATE_FORMAT));
        return Date.from(Instant.from(localDate.atStartOfDay(ZoneId.systemDefault())));
    }

    public static long toUnix(String dateStr) {
        return toDate(dateStr).toInstant().getEpochSecond();
    }

    public static String toStr(long unixTime) {
        return Instant.ofEpochSecond(unixTime).atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern(Const.DEF_DATE_FORMAT));
    }

    public static String md2Html(String content) {
        return new PegDownProcessor(Extensions.ALL_WITH_OPTIONALS).markdownToHtml(content);
    }

    public static <T> List<T> newArrayList() {
        return new ArrayList<>();
    }

    public static <T> List<T> newArrayList(int size) {
        return new ArrayList<>(size);
    }

    public static <T> boolean notEmpty(Collection<T> collection) {
        return null != collection && !collection.isEmpty();
    }

    public static <T> List<T> jsonToList(String json, Class<T> tClass) {
        ObjectMapper mapper = Jackson.getJson().getObjectMapper();
        JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, tClass);
        try {
            return mapper.readValue(json, javaType);
        } catch (Exception e) {
            e.printStackTrace();
            return newArrayList();
        }
    }

    public static String toJson(Object obj) {
        return Jackson.getJson().toJson(obj);
    }
}
